Skip to content

Conversation

@DarkMatter-999
Copy link

Trac ticket: https://core.trac.wordpress.org/ticket/57469

The PR ensures that any NULL values in the sidebars_widgets array are replaced with empty arrays during widget retrieval and mapping.

This is needed as PHP 8.x introduces stricter type and warning behaviors that can break assumptions made in earlier versions.

Code used to testing:

DELETE FROM `wp_options` WHERE `option_name` = 'sidebars_widgets';
INSERT INTO `wp_options` (`option_name`, `option_value`, `autoload`) VALUES ('sidebars_widgets','a:2:{s:19:"wp_inactive_widgets";N;s:9:"sidebar-1";N;}','yes');

Before:

sidebar-null-values-before.mov

After:

sidebar-null-values-after.mov

@github-actions
Copy link

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • The Plugin and Theme Directories cannot be accessed within Playground.
  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@DarkMatter-999 DarkMatter-999 marked this pull request as ready for review August 27, 2025 09:25
@github-actions
Copy link

github-actions bot commented Aug 27, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props lakshyajeet, westonruter, mindctrl.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@mindctrl
Copy link

mindctrl commented Sep 8, 2025

@DarkMatter-999 thanks for adding phpunit tests.

Here's my test report for this PR:

Test Report

Description

This report validates whether the indicated patch works as expected.

Patch tested: #9603

Environment

  • WordPress: 6.9-alpha-60093-src
  • PHP: 8.2.29
  • Server: nginx/1.29.0
  • Database: mysqli (Server: 8.4.6 / Client: mysqlnd 8.2.29)
  • Browser: Chrome 140.0.0.0
  • OS: macOS
  • Theme: Twenty Twenty-Five 1.3
  • MU Plugins:
    • phpmailer.php
  • Plugins:
    • Test Reports 1.2.0

Actual Results

  1. ✅ Issue resolved with patch.

Additional Notes

  • Without this patch, once the fatal error happens, the site is inoperable until a manual fix is applied.
  • Since it's unclear how the sidebar widgets get set to null in some cases, I manually created wp_options.sidebars_widgets with a sidebar containing a null value using the MySQL commands in the description above.

Delete existing config

mysql> DELETE FROM `wp_options` WHERE `option_name` = 'sidebars_widgets';
Query OK, 1 row affected (0.00 sec)

Insert config with null values

mysql> INSERT INTO `wp_options` (`option_name`, `option_value`, `autoload`) VALUES ('sidebars_widgets','a:2:{s:19:"wp_inactive_widgets";N;s:9:"sidebar-1";N;}','yes');
Query OK, 1 row affected (0.00 sec)

Get config to confirm new values

mysql> select * from wp_options where option_name = 'sidebars_widgets';
+-----------+------------------+-------------------------------------------------------+----------+
| option_id | option_name      | option_value                                          | autoload |
+-----------+------------------+-------------------------------------------------------+----------+
|       175 | sidebars_widgets | a:2:{s:19:"wp_inactive_widgets";N;s:9:"sidebar-1";N;} | yes      |
+-----------+------------------+-------------------------------------------------------+----------+
1 row in set (0.00 sec)

Get config after switching themes in wp-admin

mysql> select * from wp_options where option_name = 'sidebars_widgets';
+-----------+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+
| option_id | option_name      | option_value                                                                                                                                                                                                                                                             | autoload |
+-----------+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+
|       175 | sidebars_widgets | a:7:{s:19:"wp_inactive_widgets";a:5:{i:0;s:7:"block-2";i:1;s:7:"block-3";i:2;s:7:"block-4";i:3;s:7:"block-5";i:4;s:7:"block-6";}s:9:"sidebar-1";a:0:{}s:9:"sidebar-2";a:0:{}s:9:"sidebar-3";a:0:{}s:9:"sidebar-4";a:0:{}s:9:"sidebar-5";a:0:{}s:13:"array_version";i:3;} | yes      |
+-----------+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------+
1 row in set (0.00 sec)

mysql> 


// Replace null values inside the array with an empty array.
foreach ( $sidebars_widgets as $key => $value ) {
if ( null === $value ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if it was set to something other than an array or null, like a string, boolean, integer, or object? Wouldn't this be more appropriate:

Suggested change
if ( null === $value ) {
if ( ! is_array( $value ) ) {

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moving forward with this approach


// Replace null values inside the array with an empty array.
foreach ( $new_sidebars_widgets as $key => $value ) {
if ( null === $value ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if ( null === $value ) {
if ( ! is_array( $value ) ) {

Comment on lines 1353 to 1358
// Replace null values inside the array with an empty array.
foreach ( $sidebars_widgets as $key => $value ) {
if ( null === $value ) {
$sidebars_widgets[ $key ] = array();
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively:

Suggested change
// Replace null values inside the array with an empty array.
foreach ( $sidebars_widgets as $key => $value ) {
if ( null === $value ) {
$sidebars_widgets[ $key ] = array();
}
}
$sidebars_widgets = array_filter( $sidebars_widgets, 'is_array' );

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think checking for is_array will be a better solution and is a drop in replacement because it preserves sidebar keys and guarantees any downstream operations receive arrays, this is consistent with how older PHP version like 7.4 handle array_merge and array_search.

Using array_filter($sidebars_widgets, 'is_array') will remove entries that are not arrays, which can drop keys and change control flow in the downstream code that expects those keys to exist.

Comment on lines 1521 to 1526
// Replace null values inside the array with an empty array.
foreach ( $new_sidebars_widgets as $key => $value ) {
if ( null === $value ) {
$new_sidebars_widgets[ $key ] = array();
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively:

Suggested change
// Replace null values inside the array with an empty array.
foreach ( $new_sidebars_widgets as $key => $value ) {
if ( null === $value ) {
$new_sidebars_widgets[ $key ] = array();
}
}
$new_sidebars_widgets = array_filter( $new_sidebars_widgets, 'is_array' );

Copy link
Member

@westonruter westonruter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. Just a minor suggestion to merge a couple assertions.

@github-actions
Copy link

A commit was made that fixes the Trac ticket referenced in the description of this pull request.

SVN changeset: 60732
GitHub commit: c683208

This PR will be closed, but please confirm the accuracy of this and reopen if there is more work to be done.

@github-actions github-actions bot closed this Sep 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants